/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

//#ifndef INTERSECT
//#define INTERSECT

#include <math.h>
#include <矩阵.h>
#include <向量.h>
#include <Vector/向量运算.h>
#include <SIMD/CPU_向量计算.h>

#include <线性代数/矩阵计算.h>



//射线三角形相交
bool IntersectTriangle(const float* vert1, const float* vert2, const float* vert3, const float* near, const float* far,  float* uvt);

//射线正面相交三角形
bool FrontIntersectTriangle(const float* vert1, const float* vert2, const float* vert3,
			    const float* near, const float* far,  float* uvt, bool isFrant=true);

//int32 f_IntersectTriangle(const vec3& vert1, const vec3& vert2, const vec3& vert3, const vec3& N, const vec3& dir, vec3* uvt);
int32 f_graph_IntersectTriangle(const vec3& vert1, const vec3& vert2, const vec3& vert3, const vec3& S, const vec3& dir, vec3* uvt);
int32 f_graph_射线三角形相交(const vec3& vert, const vec3& 边A, const vec3& 边B, const vec3& S, const vec3& dir, vec3* uvt);



//根据UVT取得焦点位置
inline void Intersect_uvtPos(const float vert1[3], const float vert2[3], const float vert3[3], const float uvt[3], float point[3]){
	float vecAB[3] = {0.0,0.0,0.0};
	float vecAC[3] = {0.0,0.0,0.0};
	vec_相减(vecAB, vert2, vert1);
	vec_相减(vecAC, vert3, vert1);

	vec_自乘(vecAB, uvt[0]);
	vec_自乘(vecAC, uvt[1]);
	vec_相加(point, vert1, vecAB);
	vec_相加(point, vecAC, point);
}

//是否同侧
inline bool f_点在边同侧(const float*  A, const float*  B, const float*  C, const float*  P){
	float AB[3] = {B[0] - A[0], B[1] - A[1], B[2] - A[2]};
	float AC[3] = {C[0] - A[0], C[1] - A[1], C[2] - A[2]};
	float AP[3] = {P[0] - A[0], P[1] - A[1], P[2] - A[2]};
	//Vector_normalize(AB);
	//Vector_normalize(AC);
	//Vector_normalize(AP);
	//Vector3 v1 = AB.Cross(AC) ;
	float v1[3] = {0.0, 0.0, 0.0};
	vec_叉积(v1, AB, AC);
	//Vector3 v2 = AB.Cross(AP) ;
	float v2[3] = {0.0, 0.0, 0.0};
	vec_叉积(v2, AB, AP);

	// v1 and v2 should point to the same direction
	//return v1.Dot(v2) >= 0 ;
	return vec_dot(v1, v2) >= 0;
}

inline bool f_点在边同侧(const vec3& A, const vec3& B, const vec3& C, const vec3& P) {
	vec3 AB = B - A;
	vec3 AC = C - A;
	vec3 AP = P - A;
	//Vector_normalize(AB);
	//Vector_normalize(AC);
	//Vector_normalize(AP);
	//Vector3 v1 = AB.Cross(AC) ;
	vec3 v1 { 0.0, 0.0, 0.0 };
	v1 = vec_cross(AB, AC);
	//Vector3 v2 = AB.Cross(AP) ;
	vec3 v2 = { 0.0, 0.0, 0.0 };
	v2 = vec_cross(AB, AP);
	

	// v1 and v2 should point to the same direction
	//return v1.Dot(v2) >= 0 ;
	return vec_dot(v1, v2) >= 0;
}


inline bool f_点是否在三角形内(const float* A, const float* B, const float* C, const float* P) {
    return f_点在边同侧(A, B, C, P) && f_点在边同侧(B, C, A, P) && f_点在边同侧(C, A, B, P) ;
}

bool PointinTriangle(const float* A, const float* B, const float* C, const float* P);




//两线段距离
Inline float f_graph_两线段距离(const float* vec0, const float* vec1) {
	float normal[3] = { 0.0, 0.0, 0.0 };
	vec_叉积(normal, vec0, vec1);
	float dot = vec_dot(vec0, vec1);
	return dot / 向量_两向量距离(normal);
}




int32	f_UpProject还原空间顶点(const vec3* xyz, const float32* 投影矩阵, const float32* 模型矩阵, const vec4* viewport, vec4* vert);
vec3	f_UpProject还原空间顶点(const vec3& xyz, const Mat44& 投影矩阵, const Mat44& 视图矩阵, const S_Rect2Df& viewport);
vec3	f_UpProject还原空间顶点(const vec3& xyz, const Mat44f& 投影矩阵, const Mat44f& 视图逆矩阵, const S_Rect2Df& viewport);
vec2	f_Project空间坐标转屏幕(const Mat44& 投影矩阵, const Mat44& 视图矩阵, const vec3& 中心坐标, const S_Rect2Df& rect);



//bool	f_graph_AABB射线相交(const vec3& start, const vec3& dir, const vec3& min, const vec3& max, float32& t);

void f_Voxelize遮罩(const Vec3* 顶点, int 顶点num, const uint32* 索引, int 索引数量, uint32 width, uint32 height, uint32 depth, uint8* volume, Vec3 minExtents, Vec3 maxExtents);



bool f_graph_点是否在矩形内(const S_Rect2Df& rect, vec2* v, uint32 num);

int32 f_graph_线段相交(const S_Line& 主线, const vec2* lines, uint32 num);


//抄了NV的 FleX IntersectRayAABBOmpf
bool f_graph_射线AABB相交(const vec3& s, const vec3& dir, const S_Bounding& box, float32* t = nullptr);

bool f_graph_射线与变换AABB相交(const S_Bounding& box, const vec3& s, const vec3& dir, vec3* 相交坐标, float32* 相交距离);



//判断两线段相交
/*bool IsIntersect(double px1, double py1, double px2, double py2, double px3, double py3, double px4, double py4)
{
	bool flag = false;
	double d = (px2 - px1) * (py4 - py3) - (py2 - py1) * (px4 - px3);
	if (d != 0)
	{
		double r = ((py1 - py3) * (px4 - px3) - (px1 - px3) * (py4 - py3)) / d;
		double s = ((py1 - py3) * (px2 - px1) - (px1 - px3) * (py2 - py1)) / d;
		if ((r >= 0) && (r <= 1) && (s >= 0) && (s <= 1))
		{
			flag = true;
		}
	}
	return flag;
}*/


